#include <Arduino.h>
#include <FastLED.h>
#include "chinese_font.h"

#define NUM_LEDS       256
#define WS2812_PIN      18
#define MAX_BRIGHTNESS  30

#define DISPLAY_MODE    1   //display_mode：0-English 1-Chinese 2-Mixtrue

enum{
    MATRIX_COLUMN_SCAN, //列扫描
    //MATRIX_ROW_SCAN,    //行扫描
    MATRIX_ZAGZAG_SCAN,  //列Z字扫描  
    MATRIX_ZAGZAG2_SCAN, //行Z字扫描
};

// !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
//凉州词二首·其一，王翰、葡萄美酒夜光杯，欲饮琵琶马上催。醉卧沙场君莫笑，古来征战几人回？

CRGB leds[NUM_LEDS];
uint8_t font_num = 0;
const uint8_t matrix_type = MATRIX_COLUMN_SCAN; //点阵扫描类型，根据实际情况修改，默认列扫描

void ArrayToCRGB(const uint8_t *pbuf,CRGB *rgb);
void Array1ToCRGB(const uint8_t *pbuf,CRGB *rgb);
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);  
#if DISPLAY_MODE
  font_num = sizeof(ws2812_font_table)/(NUM_LEDS*3); //Default only detect chinese font.
  printf("Detect chinese font num: %d\n",font_num);   
#else
  font_num = sizeof(ws2812_font_table)/(NUM_LEDS/2*3); //English font
  printf("Detect english font num: %d\n",font_num); 
#endif  
  
  FastLED.addLeds<NEOPIXEL, WS2812_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(MAX_BRIGHTNESS);
  FastLED.clear();
  //Serial.printf("Hello FastLED !\n");
}

void loop() {
  // put your main code here, to run repeatedly:
   for(uint8_t i=0;i<font_num;i++){
#if DISPLAY_MODE
      ArrayToCRGB(&ws2812_font_table[NUM_LEDS*3*i],(CRGB *)&leds);
#else
      Array1ToCRGB(&ws2812_font_table[NUM_LEDS/2*3*i],(CRGB *)&leds);
#endif
      FastLED.show();
      delay(500);
   } 
}
//Chinese font to CRGB
void ArrayToCRGB(const uint8_t *pbuf,CRGB *rgb)
{
   uint16_t i = 0; 
   uint16_t ii = 0;
   uint8_t j = 0;
   uint8_t k = 0;
   CRGB temp_rgb[NUM_LEDS];
   
   for(i=0;i<NUM_LEDS;i++)
   {
      if(matrix_type == MATRIX_COLUMN_SCAN){
          rgb[i].red = *(pbuf+3*i);
          rgb[i].green = *(pbuf+3*i+1);
          rgb[i].blue = *(pbuf+3*i+2);
      }else if(matrix_type == MATRIX_ZAGZAG_SCAN){
          j = i/16;
          k = i%16;
          switch(j%2)
          {
             case 0:
               rgb[i].red = *(pbuf+3*i);
               rgb[i].green = *(pbuf+3*i+1);
               rgb[i].blue = *(pbuf+3*i+2);
               break;
             case 1:
               ii = 16*j+(15-k);
               rgb[i].red = *(pbuf+3*ii);
               rgb[i].green = *(pbuf+3*ii+1);
               rgb[i].blue = *(pbuf+3*ii+2);
               break;
          }
      }else{//ZAGZAG2
          j = i/16;
          k = i%16;
          switch(j%2)
          {
             case 1:
               rgb[i].red = *(pbuf+3*i);
               rgb[i].green = *(pbuf+3*i+1);
               rgb[i].blue = *(pbuf+3*i+2);
               break;
             case 0:
               ii = 16*j+(15-k);
               rgb[i].red = *(pbuf+3*ii);
               rgb[i].green = *(pbuf+3*ii+1);
               rgb[i].blue = *(pbuf+3*ii+2);
               break;
          }
      }   
   }   
}
//English font to CRGB
void Array1ToCRGB(const uint8_t *pbuf,CRGB *rgb)
{
   uint16_t i = 0;  
   uint16_t ii = 0;
   uint8_t j = 0;
   uint8_t k = 0;   
   CRGB temp_rgb[NUM_LEDS];

   for(i=0;i<(NUM_LEDS/2);i++)
   {
      if(matrix_type == MATRIX_COLUMN_SCAN){
          rgb[16*4+i].red = *(pbuf+3*i);
          rgb[16*4+i].green = *(pbuf+3*i+1);
          rgb[16*4+i].blue = *(pbuf+3*i+2);
      }else if(matrix_type == MATRIX_ZAGZAG_SCAN){
          j = i/16;
          k = i%16;
          switch(j%2)
          {
              case 0:
                rgb[16*4+i].red = *(pbuf+3*i);
                rgb[16*4+i].green = *(pbuf+3*i+1);
                rgb[16*4+i].blue = *(pbuf+3*i+2);
                break;
              case 1:
                ii = 16*j+(15-k);
                rgb[16*4+i].red = *(pbuf+3*ii);
                rgb[16*4+i].green = *(pbuf+3*ii+1);
                rgb[16*4+i].blue = *(pbuf+3*ii+2);
                break;
          }
      }else{//ZAGZAG2
          j = i/16;
          k = i%16;
          switch(j%2)
          {
              case 1:
                rgb[16*4+i].red = *(pbuf+3*i);
                rgb[16*4+i].green = *(pbuf+3*i+1);
                rgb[16*4+i].blue = *(pbuf+3*i+2);
                break;
              case 0:
                ii = 16*j+(15-k);
                rgb[16*4+i].red = *(pbuf+3*ii);
                rgb[16*4+i].green = *(pbuf+3*ii+1);
                rgb[16*4+i].blue = *(pbuf+3*ii+2);
                break;
          }
      }
   }  
}

